﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using dbPoll_Application.ViewModels;
using dbPoll_Application.Models;
using System.Web.Routing;
using dbPoll_Application.Helpers;
using NHibernate;
using System.Web.Security;

namespace dbPoll_Application.Controllers
{
    public class ParticipantController : Controller
    {
        [Authorize]
        public bool Delete(int participantID)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                ParticipantRepository.GetParticipantByParticipantID(participantID).group=null;
                transaction.Commit();
                return transaction.WasCommitted;
            }
        }

        [Authorize]
        public ActionResult Details(int participantID, int pollID, String pollName)
        {
            return View(new DetailsViewModel(participantID, pollID));
        }

        [Authorize]
        [HttpPost]
        public ActionResult Details(int participantID, int pollID)
        {
            string[] participants=new String[0];
            if (Request.Form["participants"]!=null) participants = Request.Form["participants"].Split(',');
            foreach (string participant in participants) 
                ParticipantRepository.GetParticipantByParticipantID(int.Parse(participant)).group = 
                    ParticipantRepository.GetGroupByGroupID(participantID);
            PollRepository.UpdatePoll(PollRepository.GetPollByID(pollID));
            return View(new DetailsViewModel(participantID,pollID));
        }
        
        [Authorize]
        public ActionResult EditList(int pollID, String pollName)
        {
            var poll = PollRepository.GetPollByID(pollID);
            if (poll.isGroup)
            {
                return RedirectToAction("EditGroupList", new { pollID = pollID, pollName = pollName });
            }
            return View(new EditParticipantsViewModel(poll));
        }
        [Authorize]
        public ActionResult EditGroupList(int pollID, String pollName)
        {
            return View(new ParticipantFieldViewModel(PollRepository.GetPollByID(pollID)));
        }

        [Authorize]
        public ActionResult SaveList(EditParticipantsViewModel p)
        {
            foreach (var editParticipantViewModel in p.Participants)
            {
                var participant = ParticipantRepository.GetParticipantByParticipantID(editParticipantViewModel.ParticipantID);
                if (editParticipantViewModel.Fields != null)
                {
                    foreach (var field in editParticipantViewModel.Fields)
                    {
                        if (field.Value != null && field.Value != String.Empty)
                        {
                            var participantField = ParticipantRepository.GetFieldByID(field.FieldID);
                            ParticipantFieldValue fieldValue = null;
                            if (participantField != null) fieldValue = participantField.fieldValues.Where(m => m.participant == participant).FirstOrDefault<ParticipantFieldValue>();
                            if (fieldValue == null && participantField != null)
                            {
                                fieldValue = new ParticipantFieldValue(participant, field.Value);
                                participantField.fieldValues.Add(fieldValue);
                                ParticipantRepository.UpdateFields(participantField);
                            }
                            else if (!fieldValue.value.Equals(field.Value))
                            {
                                fieldValue.value = field.Value;
                                ParticipantRepository.UpdateFields(participantField);
                            }
                        }
                    }
                }
                if (editParticipantViewModel.Entity != null)
                {
                    participant.entity = EntityRepository.GetEntityByEntityID(editParticipantViewModel.Entity.entityID);
                    
                }
                participant.deviceID = editParticipantViewModel.DeviceID;
                participant.firstName = editParticipantViewModel.FirstName;
                participant.lastName = editParticipantViewModel.LastName;
                participant.votingWeight = editParticipantViewModel.VotingWeight;
                ParticipantRepository.Update(participant);
            }
            return RedirectToAction("EditList", new { pollID = p.PollID, pollName = p.PollName });
        }

        [Authorize]
        public Boolean EditingList(int participantID, int fieldID, String value, int pollID)
        {
            Poll poll = PollRepository.GetPollByID(pollID);
            ParticipantField field = ParticipantRepository.GetParticipantFieldByID(fieldID);
            ParticipantFieldValue participantsfield = null;
            if (poll.isGroup) participantsfield = field.fieldValues.SingleOrDefault(val => (val.groupd!=null && val.groupd.groupID == participantID));
            else participantsfield = field.fieldValues.SingleOrDefault(val => (val.participant!=null && val.participant.participantID == participantID));
            if (participantsfield!=null) { participantsfield.value = value; }
            else 
            {
                if (poll.isGroup) field.fieldValues.Add(new ParticipantFieldValue(ParticipantRepository.GetGroupByGroupID(participantID), value));
                else field.fieldValues.Add(new ParticipantFieldValue(ParticipantRepository.GetParticipantByParticipantID(participantID), value));
            }
            return ParticipantRepository.UpdateFields(field);
        }

        [Authorize]
        public Boolean EditingEntity(int pollID, int participantID, int value)
        {
            if (PollRepository.GetPollByID(pollID).isGroup)
            {
                ParticipantGroup group = ParticipantRepository.GetGroupByGroupID(participantID);
                group.entity = EntityRepository.GetEntityByEntityID(value);
                return ParticipantRepository.Update(group);
            }
            else
            {
                Participant participant = ParticipantRepository.GetParticipantByParticipantID(participantID);
                participant.entity = EntityRepository.GetEntityByEntityID(value);
                return ParticipantRepository.Update(participant);
            }            
        }
        [Authorize]
        public Boolean AddGroup(int pollID, String name)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                ParticipantGroup group = new ParticipantGroup(name);
                PollRepository.GetPollByID(pollID).groups.Add(group);
                session.SaveOrUpdate(group);
                transaction.Commit();
                return transaction.WasCommitted;
            }
        }

        [Authorize]
        public Boolean AddField(int pollID, String name)
        {
            ParticipantField field = new ParticipantField(name);
            PollRepository.GetPollByID(pollID).participantFields.Add(field);
            return ParticipantRepository.UpdateFields(field);
        }
        [Authorize]
        public Boolean DeleteField(int pollID, int fieldID)
        {
            ParticipantField field = ParticipantRepository.GetParticipantFieldByID(fieldID);
            PollRepository.GetPollByID(pollID).participantFields.Remove(field);
            return ParticipantRepository.DeleteFields(field);
        }
        [Authorize]
        public ActionResult AddWeb(int pollID, String pollName)
        {
            IList<User> users = UserRepository.GetUsersUserCanManage(User.Identity.Name).
                Where(u => u.IsGeneric).ToList();
            IList<SelectListItem> use=new List<SelectListItem>();
            foreach (User u in users) use.Add(new SelectListItem() { Value=u.UserName, Text = u.UserName });
            return View(new ParticipantFieldViewModel(PollRepository.GetPollByID(pollID),use.AsEnumerable<SelectListItem>()));
        }
        [Authorize]
        public String AddEmail(String email, int pollID)
        {
            var poll = PollRepository.GetPollByID(pollID);
            var participants = poll.participants;
            int participantCount = ParticipantRepository.GetTotalParticipantCount();
            if (participants.Any(part => (part.linkedUser != null && part.linkedUser.Email.Equals(email))))
                return "User already added";
            var users = UserRepository.GetUsersUserCanManage(User.Identity.Name);
            var user = users.FirstOrDefault(use => use.Email.Equals(email));
            if (user!=null)
            {
                if (!user.Roles.Contains(RoleRepository.GetRoleByName("Poll User"))) 
                    user.Roles.Add(RoleRepository.GetRoleByName("Poll User"));
                user.IsDeleted = false;
                UserRepository.Update(user);
            }
            else
            {
                var trial = UserRepository.GetUserByEmail(email);
                if (trial == null || trial.UserName.Equals(String.Empty)) trial=null;
                else if (!trial.Roles.Contains(RoleRepository.GetRoleByName("System Administrator")) &&
                    !trial.Roles.Contains(RoleRepository.GetRoleByName("Poll Master"))) trial=null;
                if (trial!=null)
                {
                    user = trial;
                    if (!user.Roles.Contains(RoleRepository.GetRoleByName("Poll User")))
                        user.Roles.Add(RoleRepository.GetRoleByName("Poll User"));
                    user.IsDeleted = false;
                    UserRepository.Update(user);
                }
            }
            if (user==null) return "No such user";
            participants.Add(new Participant("0" + (900000 + participantCount).ToString("X"),ParticipantType.Web,user, user.FirstName,user.LastName));
            if (PollRepository.UpdatePoll(poll)) return "Success";
            else return "Unsuccessful";
        }

        [Authorize]
        public String AddBulk(String bulk, int pollID)
        {
            var poll = PollRepository.GetPollByID(pollID);
            var participants = poll.participants;
            int participantCount = ParticipantRepository.GetTotalParticipantCount();
            User user = UserRepository.GetUserByUsername(bulk);
            if (participants.Any(part => (part.linkedUser != null && part.linkedUser.Equals(user))))
                return "User already added";
            participants.Add(new Participant("0" + (100000 + participantCount).ToString("X"), ParticipantType.Generic, user,null,null));
            if (PollRepository.UpdatePoll(poll)) return "Success";
            else return "Unsuccessful";
        }
        [Authorize]
        public Boolean AddKeypadUser(String deviceID, int pollID)
        {
            var poll = PollRepository.GetPollByID(pollID);
            if (deviceID == null || deviceID == String.Empty)
            {
                return false;
            }
            if (poll.participants.Where(m => m.deviceID == deviceID).Count() > 0)
            {
                return false;
            }
            var participant = new Participant(deviceID, ParticipantType.Keypad, String.Empty, String.Empty);
            poll.participants.Add(participant);
            return PollRepository.UpdatePoll(poll);
        }

        [Authorize]
        public Boolean SendPublicMessage(String messageText, int pollID)
        {
            var poll = PollRepository.GetPollByID(pollID);
            var participants = poll.participants.Where(m => m.linkedUser != null);
            var users = from p in participants select p.linkedUser; 
            var message = new Message(messageText, users.ToList<User>());
            poll.messages.Add(message);

            return PollRepository.UpdatePoll(poll);
        }

        [Authorize]
        public Boolean SendPrivateMessage(String messageText, String username, int pollID)
        {
            var poll = PollRepository.GetPollByID(pollID);
            var user = UserRepository.GetUserByUsername(username);
            var message = new Message(messageText, user);
            poll.messages.Add(message);

            return PollRepository.UpdatePoll(poll);
        }

        [Authorize]
        public Boolean AddTestParticipant(String deviceID, int pollID)
        {
            var poll = PollRepository.GetPollByID(pollID);
            var user = UserRepository.GetUserByUsername(User.Identity.Name);
            var participant = new Participant(deviceID, ParticipantType.Keypad, user, user.FirstName, user.LastName);
            participant.isTestParticipant = true;
            if (poll.participants.Where(m => m.deviceID == deviceID).Count<Participant>() > 0)
            {
                return false;
            }
            if (poll.participants.Any(p => p.linkedUser != null && p.linkedUser.Equals(user))) return false;
            poll.participants.Add(participant);
            return PollRepository.UpdatePoll(poll);
        }
        [Authorize]
        public ActionResult EditGroup(int groupID, int pollID)
        {
            Poll poll = PollRepository.GetPollByID(pollID);
            ParticipantGroup group = ParticipantRepository.GetGroupByGroupID(groupID);
            return View(new ParticipantFieldViewModel(poll,group));
        }

        public void MarkAsAttended(String deviceID,int pollID)
        {
            var participant = ParticipantRepository.GetParticipantByDeviceIDAndPoll(deviceID, PollRepository.GetPollByID(pollID));
            participant.attended = true;
            ParticipantRepository.Update(participant);
        }
    }
}
